home *** CD-ROM | disk | FTP | other *** search
/ Aminet 50 / Aminet 50 (2002)(GTI - Schatztruhe)[!][Aug 2002].iso / Aminet / util / libs / mpega_libmad.lha / mpega_libmad / library_init.c < prev    next >
C/C++ Source or Header  |  2001-12-18  |  25KB  |  897 lines

  1. #include "library_init.h"
  2.  
  3. #include <exec/memory.h>
  4. #include <exec/resident.h>
  5. #include <exec/initializers.h>
  6.  
  7. #include "wrap_mpega.h"
  8.  
  9. #ifdef BUILD_POWERUP
  10. #include <proto/ppc.h>
  11. #include "support_pup.h"
  12. #elif defined(BUILD_WARPUP)
  13. #include <powerpc/powerpc.h>
  14. #include <proto/powerpc.h>
  15. #include "support.h"
  16. #else
  17. #include "support.h"
  18. #endif
  19.  
  20. #ifdef BUILD_WARPUP
  21. #define CallPPCFunc(func, p1, p2) \
  22. ({struct PPCArgs args; \
  23.     args.PP_Flags = PPF_LINEAR; \
  24.     args.PP_Stack = NULL; \
  25.     args.PP_StackSize = 0; \
  26.     args.PP_Code = (APTR)func; \
  27.     args.PP_Offset = 0; \
  28.     args.PP_Regs[0] = (ULONG)p1; \
  29.     args.PP_Regs[1] = (ULONG)p2; \
  30.     RunPPC(&args); \
  31.     args.PP_Regs[0]; \
  32. })
  33.  
  34. struct MPEGABase
  35. {
  36.     struct Library lib;
  37. };
  38.  
  39. #pragma libbase MPEGABase
  40.  
  41. const char LibVersionString[] = "$VER: " LIB_ID;
  42. const char LibNameString[] = LIB_NAME;
  43.  
  44. void INIT_3_InitLibraries(__REGA6(struct Library *base))
  45. {
  46.     /* At least v15.0 is needed for PPF_LINEAR */
  47.     if (PowerPCBase->lib_Version >= 15) {
  48.         if (CallPPCFunc(InitSupport, 0, 0))
  49.             return;
  50.     }
  51.     abortLibInit();
  52. }
  53.  
  54. void EXIT_3_InitLibraries(__REGA6(struct Library *base))
  55. {
  56.     if (PowerPCBase->lib_Version >= 15)
  57.         CallPPCFunc(RemoveSupport, 0, 0);
  58. }
  59. #else
  60. /* Reserved library-function and dummy entrypoint */
  61. LONG LIB_Reserved(void)
  62. {
  63.     return 0;
  64. }
  65.  
  66. struct ExecBase *SysBase;
  67. struct DosLibrary *DOSBase;
  68.  
  69. ULONG LibVectors[] = {
  70. #ifdef __MORPHOS__
  71.     FUNCARRAY_32BIT_NATIVE,
  72. #endif
  73.     (ULONG) &LIB_Open,
  74.     (ULONG) &LIB_Close,
  75.     (ULONG) &LIB_Expunge,
  76.     (ULONG) &LIB_Reserved,
  77.  
  78.     (ULONG) &LIB_MPEGA_open,
  79.     (ULONG) &LIB_MPEGA_close,
  80.     (ULONG) &LIB_MPEGA_decode_frame,
  81.     (ULONG) &LIB_MPEGA_seek,
  82.     (ULONG) &LIB_MPEGA_time,
  83.     (ULONG) &LIB_MPEGA_find_sync,
  84.     (ULONG) &LIB_MPEGA_scale,
  85.     0xFFFFFFFF
  86. };
  87.  
  88. struct LibInitStruct
  89. {
  90.     ULONG    LibSize;
  91.     void    *FuncTable;
  92.     void    *DataTable;
  93.     void    (*InitFunc)(void);
  94. };
  95.  
  96. struct LibInitStruct LibInitStruct = {
  97.     sizeof(struct PrivateBase),
  98.     LibVectors,
  99.     NULL,
  100.     (void (*)(void)) &LibInit
  101. };
  102.  
  103. static const char LibVersion[] = "$VER: " LIB_ID;
  104.  
  105. static const struct Resident RomTag __attribute__((__aligned__(2))) = {
  106.     RTC_MATCHWORD,
  107.     &RomTag,
  108.     &RomTag + 1,
  109. #ifdef __MORPHOS__
  110.     RTF_PPC | RTF_AUTOINIT,
  111. #else
  112.     RTF_AUTOINIT,
  113. #endif
  114.     LIB_VERSION,
  115.     NT_LIBRARY,
  116.     0,
  117.     LIB_NAME,
  118.     &LibVersion[6],
  119.     &LibInitStruct
  120. };
  121.  
  122.  
  123. #ifdef __MORPHOS__
  124. ULONG __amigappc__ = 1;
  125. #endif
  126.  
  127.  
  128. static void LibCleanup(struct PrivateBase *PrivateBase)
  129. {
  130. #ifdef BUILD_POWERUP
  131.     RemoveSupport(PrivateBase);
  132. #else
  133.     RemoveSupport();
  134. #endif
  135.  
  136.     if (DOSBase)
  137.     {
  138.         CloseLibrary((struct Library *)DOSBase);
  139.         PrivateBase->pv_DOSBase = DOSBase = NULL;
  140.     }
  141. }
  142.  
  143. BPTR LibExpunge(struct PrivateBase *PrivateBase)
  144. {
  145. #ifdef BUILD_POWERUP
  146.     if (PrivateBase->ParentBase)
  147.     {
  148.         struct PrivateBase *OldBase = PrivateBase;
  149.  
  150.         PrivateBase = PrivateBase->ParentBase;
  151.  
  152.         FreeMem((APTR)((ULONG)(OldBase) - (ULONG)(OldBase->pv_Lib.lib_NegSize)),
  153.                 OldBase->pv_Lib.lib_NegSize + OldBase->pv_Lib.lib_PosSize);
  154.     }
  155. #endif
  156.  
  157.     if ((PrivateBase->pv_Lib.lib_OpenCnt == 0))
  158.     {
  159.         BPTR seglist;
  160.  
  161.         seglist = PrivateBase->pv_SegList;
  162.         Remove(&PrivateBase->pv_Lib.lib_Node);
  163.         LibCleanup(PrivateBase);
  164.  
  165.         FreeMem((APTR)((ULONG)(PrivateBase) - (ULONG)(PrivateBase->pv_Lib.lib_NegSize)),
  166.                 PrivateBase->pv_Lib.lib_NegSize + PrivateBase->pv_Lib.lib_PosSize);
  167.  
  168.         return seglist;
  169.     } else PrivateBase->pv_Lib.lib_Flags |= LIBF_DELEXP;
  170.  
  171.     return 0L;
  172. }
  173.  
  174. #ifdef __MORPHOS__
  175. struct Library *LibInit(struct PrivateBase *PrivateBase, BPTR SegList, struct ExecBase *sysbase)
  176. #else
  177. struct Library * ASM LibInit(REG(d0, struct PrivateBase *PrivateBase), REG(a0, BPTR SegList), REG(a6, struct ExecBase *sysbase))
  178. #endif
  179. {
  180.     SysBase = sysbase;
  181.  
  182.     if ((DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 36)))
  183.     {
  184. #ifdef BUILD_POWERUP
  185.         if (InitSupport(PrivateBase))
  186. #else
  187.         if (InitSupport())
  188. #endif
  189.         {
  190.             PrivateBase->pv_Lib.lib_Revision     = LIB_REVISION;
  191.             PrivateBase->pv_SegList              = SegList;
  192.             PrivateBase->pv_SysBase              = SysBase;
  193.             PrivateBase->pv_DOSBase              = DOSBase;
  194. #ifdef BUILD_POWERUP
  195.             PrivateBase->ParentBase              = NULL;
  196. #endif
  197.  
  198.             return &PrivateBase->pv_Lib;
  199.         }
  200.     }
  201.  
  202.     LibCleanup(PrivateBase);
  203.     return NULL;
  204. }
  205.  
  206. #ifdef __MORPHOS__
  207. struct Library *LIB_Open(void)
  208. {
  209.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  210. #else
  211. struct Library * ASM LIB_Open(REG(a6, struct PrivateBase *PrivateBase))
  212. {
  213. #endif
  214. #ifdef BUILD_POWERUP
  215.     if (PrivateBase->pv_Lib.lib_OpenCnt > 0)
  216.     {
  217.         struct PrivateBase *NewBase;
  218.         ULONG BaseSize = PrivateBase->pv_Lib.lib_NegSize + PrivateBase->pv_Lib.lib_PosSize;
  219.  
  220.         if ((NewBase = AllocMem(BaseSize, MEMF_PUBLIC)))
  221.         {
  222.             CopyMem((APTR)((ULONG)PrivateBase - (ULONG)PrivateBase->pv_Lib.lib_NegSize), NewBase, BaseSize);
  223.             NewBase = (APTR)((ULONG)NewBase + (ULONG)PrivateBase->pv_Lib.lib_NegSize);
  224.  
  225.             NewBase->ParentBase = PrivateBase;
  226.             NewBase->pv_CallPPCData = NULL;
  227.             NewBase->pv_CallPPCMsg = NULL;
  228.             NewBase->pv_StartupData = NULL;
  229.             NewBase->pv_StartupMsg = NULL;
  230.             NewBase->pv_ReplyPort = NULL;
  231.             NewBase->pv_PPCPort = NULL;
  232.             NewBase->pv_Task = NULL;
  233.  
  234.             if (!InitDispatch(NewBase, MSGTYPE_HELLO))
  235.             {
  236.                 LibExpunge(NewBase);
  237.                 return NULL;
  238.             }
  239.  
  240.             PrivateBase->pv_Lib.lib_Flags &= ~LIBF_DELEXP;
  241.             PrivateBase->pv_Lib.lib_OpenCnt++;
  242.         }
  243.  
  244.         return &NewBase->pv_Lib;
  245.     } else {
  246.         if (!InitDispatch(PrivateBase, MSGTYPE_HELLO))
  247.         {
  248.             LibExpunge(PrivateBase);
  249.             return NULL;
  250.         }
  251. #endif
  252.     PrivateBase->pv_Lib.lib_Flags &= ~LIBF_DELEXP;
  253.     PrivateBase->pv_Lib.lib_OpenCnt++;
  254.  
  255.     return &PrivateBase->pv_Lib;
  256. #ifdef BUILD_POWERUP
  257.     }
  258. #endif
  259. }
  260.  
  261. #ifdef __MORPHOS__
  262. BPTR LIB_Close(void)
  263. {
  264.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  265. #else
  266. BPTR ASM LIB_Close(REG(a6, struct PrivateBase *PrivateBase))
  267. {
  268. #endif
  269. #ifdef BUILD_POWERUP
  270.     RemoveDispatch(PrivateBase, MSGTYPE_GOODBYE);
  271.  
  272.     if (PrivateBase->ParentBase)
  273.     {
  274.         struct PrivateBase *OldBase = PrivateBase;
  275.  
  276.         PrivateBase = PrivateBase->ParentBase;
  277.  
  278.         FreeMem((APTR)((ULONG)(OldBase) - (ULONG)(OldBase->pv_Lib.lib_NegSize)),
  279.                 OldBase->pv_Lib.lib_NegSize + OldBase->pv_Lib.lib_PosSize);
  280.     }
  281. #endif
  282.  
  283.     if (PrivateBase->pv_Lib.lib_OpenCnt > 0) PrivateBase->pv_Lib.lib_OpenCnt--;
  284.  
  285.     if ((PrivateBase->pv_Lib.lib_OpenCnt == 0) && (PrivateBase->pv_Lib.lib_Flags & LIBF_DELEXP))
  286.         return LibExpunge(PrivateBase);
  287.  
  288.     return 0L;
  289. }
  290.  
  291. #ifdef __MORPHOS__
  292. BPTR LIB_Expunge(void)
  293. {
  294.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  295. #else
  296. BPTR ASM LIB_Expunge(REG(a6, struct PrivateBase *PrivateBase))
  297. {
  298. #endif
  299.  
  300.     return LibExpunge(PrivateBase);
  301. }
  302. #endif /* BUILD_WARPUP */
  303.  
  304. #ifdef __MORPHOS__
  305. MPEGA_STREAM *LIB_MPEGA_open(void)
  306. {
  307.     char *stream_name = (char *)REG_A0;
  308.     MPEGA_CTRL *ctrl = (MPEGA_CTRL *)REG_A1;
  309.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  310.     struct Task *task = FindTask(NULL);
  311.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  312.  
  313.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  314.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  315.  
  316.     if ((stacksize - stackused) < stackreq)
  317.     {
  318.         char *newstack;
  319.  
  320.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return NULL;
  321.  
  322.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  323.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  324.  
  325.         PrivateBase->stackswap.Args[0] = (ULONG)stream_name;
  326.         PrivateBase->stackswap.Args[1] = (ULONG)ctrl;
  327.  
  328.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_open, &PrivateBase->stackswap.Args);
  329.         FreeVec(newstack);
  330.     } else {
  331.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_open(stream_name, ctrl);
  332.     }
  333.  
  334.     return (MPEGA_STREAM *)PrivateBase->stackswap.Return;
  335. }
  336. #else
  337. MPEGA_STREAM * LIB LIB_MPEGA_open(REG(a0, char *stream_name), REG(a1, MPEGA_CTRL *ctrl), REG(a6, struct PrivateBase *PrivateBase))
  338. {
  339. #ifdef BUILD_POWERUP
  340.     struct CallPPCData *CallPPCData;
  341.     APTR ReplyPort;
  342.     APTR CallPPCMsg;
  343.     ULONG Return;
  344.     APTR ThisTask = FindTask(NULL);
  345.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  346.  
  347.     /* Workaround for bad tasks that pass around the library base */
  348.     if (SigTask != ThisTask)
  349.     {
  350.         struct TagItem tmpTagList[1];
  351.  
  352.         tmpTagList[0].ti_Tag = TAG_DONE;
  353.         ReplyPort = PPCCreatePort(tmpTagList);
  354.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  355.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  356.     } else {
  357.         CallPPCData = PrivateBase->pv_CallPPCData;
  358.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  359.         ReplyPort = PrivateBase->pv_ReplyPort;
  360.     }
  361.  
  362.     CallPPCData->Type = MSGTYPE_CALL;
  363.     CallPPCData->PPCLVO = PPCLVO_MPEGA_open;
  364.     CallPPCData->Args[0] = (ULONG)stream_name;
  365.     CallPPCData->Args[1] = (ULONG)ctrl;
  366.  
  367.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  368.  
  369.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  370.  
  371.     PPCWaitPort(ReplyPort);
  372.     PPCGetMessage(ReplyPort);
  373.     Return = CallPPCData->Return;
  374.  
  375.     if (SigTask != ThisTask)
  376.     {
  377.         PPCDeleteMessage(CallPPCMsg);
  378.         PPCDeletePort(ReplyPort);
  379.         PPCFreeVec(CallPPCData);
  380.     }
  381.  
  382.     return (MPEGA_STREAM *)Return;
  383. #elif defined(BUILD_WARPUP)
  384.     return (MPEGA_STREAM *)CallPPCFunc(WRAP_MPEGA_open, stream_name, ctrl);
  385. #else
  386.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  387.     register char *stackptr __asm("sp");
  388.     struct Task *task;
  389.     long stackleft, stackreq = REQ_STACKSIZE;
  390.  
  391.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  392.  
  393.     MyPrivateBase->stackswap.Args[0] = (ULONG)stream_name;
  394.     MyPrivateBase->stackswap.Args[1] = (ULONG)ctrl;
  395.  
  396.     task = FindTask(NULL);
  397.     stackleft = stackptr - (char *)task->tc_SPLower;
  398.  
  399.     if (stackleft < stackreq)
  400.     {
  401.         char *newstack;
  402.  
  403.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return NULL;
  404.  
  405.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  406.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  407.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  408.  
  409.         StackSwap(&MyPrivateBase->stackswap.stack);
  410.  
  411.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_open((char *)MyPrivateBase->stackswap.Args[0], (MPEGA_CTRL *)MyPrivateBase->stackswap.Args[1]);
  412.  
  413.         StackSwap(&MyPrivateBase->stackswap.stack);
  414.  
  415.         FreeVec(newstack);
  416.         return (MPEGA_STREAM *)MyPrivateBase->stackswap.Return;
  417.     } else {
  418.         return WRAP_MPEGA_open((char *)MyPrivateBase->stackswap.Args[0], (MPEGA_CTRL *)MyPrivateBase->stackswap.Args[1]);
  419.     }
  420. #endif
  421. }
  422. #endif
  423.  
  424. #ifdef __MORPHOS__
  425. void LIB_MPEGA_close(void)
  426. {
  427.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  428. #else
  429. void LIB LIB_MPEGA_close(REG(a0, MPEGA_STREAM *mpega_stream), REG(a6, struct PrivateBase *PrivateBase))
  430. {
  431. #endif
  432. #ifdef BUILD_POWERUP
  433.     struct CallPPCData *CallPPCData;
  434.     APTR ReplyPort;
  435.     APTR CallPPCMsg;
  436.     APTR ThisTask = FindTask(NULL);
  437.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  438.  
  439.     /* Workaround for bad tasks that pass around the library base */
  440.     if (SigTask != ThisTask)
  441.     {
  442.         struct TagItem tmpTagList[1];
  443.  
  444.         tmpTagList[0].ti_Tag = TAG_DONE;
  445.         ReplyPort = PPCCreatePort(tmpTagList);
  446.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  447.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  448.     } else {
  449.         CallPPCData = PrivateBase->pv_CallPPCData;
  450.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  451.         ReplyPort = PrivateBase->pv_ReplyPort;
  452.     }
  453.  
  454.     CallPPCData->Type = MSGTYPE_CALL;
  455.     CallPPCData->PPCLVO = PPCLVO_MPEGA_close;
  456.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  457.  
  458.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  459.  
  460.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  461.  
  462.     PPCWaitPort(ReplyPort);
  463.     PPCGetMessage(ReplyPort);
  464.  
  465.     if (SigTask != ThisTask)
  466.     {
  467.         PPCDeleteMessage(CallPPCMsg);
  468.         PPCDeletePort(ReplyPort);
  469.         PPCFreeVec(CallPPCData);
  470.     }
  471. #elif defined(BUILD_WARPUP)
  472.     CallPPCFunc(WRAP_MPEGA_close, mpega_stream, 0);
  473. #else
  474.     WRAP_MPEGA_close(mpega_stream);
  475. #endif
  476. }
  477.  
  478. #ifdef __MORPHOS__
  479. LONG LIB_MPEGA_decode_frame(void)
  480. {
  481.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  482.     WORD **pcm = (WORD **)REG_A1;
  483.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  484.     struct Task *task = FindTask(NULL);
  485.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  486.  
  487.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  488.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  489.  
  490.     if ((stacksize - stackused) < stackreq)
  491.     {
  492.         char *newstack;
  493.  
  494.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  495.  
  496.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  497.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  498.  
  499.         PrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  500.         PrivateBase->stackswap.Args[1] = (ULONG)pcm;
  501.  
  502.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_decode_frame, &PrivateBase->stackswap.Args);
  503.         FreeVec(newstack);
  504.     } else {
  505.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_decode_frame(mpega_stream, pcm);
  506.     }
  507.  
  508.     return (LONG)PrivateBase->stackswap.Return;
  509. }
  510. #else
  511. LONG LIB LIB_MPEGA_decode_frame(REG(a0, MPEGA_STREAM *mpega_stream), REG(a1, WORD *pcm[MPEGA_MAX_CHANNELS]), REG(a6, struct PrivateBase *PrivateBase))
  512. {
  513. #ifdef BUILD_POWERUP
  514.     struct CallPPCData *CallPPCData;
  515.     APTR ReplyPort;
  516.     APTR CallPPCMsg;
  517.     ULONG Return;
  518.     APTR ThisTask = FindTask(NULL);
  519.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  520.  
  521.     /* Workaround for bad tasks that pass around the library base */
  522.     if (SigTask != ThisTask)
  523.     {
  524.         struct TagItem tmpTagList[1];
  525.  
  526.         tmpTagList[0].ti_Tag = TAG_DONE;
  527.         ReplyPort = PPCCreatePort(tmpTagList);
  528.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  529.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  530.     } else {
  531.         CallPPCData = PrivateBase->pv_CallPPCData;
  532.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  533.         ReplyPort = PrivateBase->pv_ReplyPort;
  534.     }
  535.  
  536.     CallPPCData->Type = MSGTYPE_CALL;
  537.     CallPPCData->PPCLVO = PPCLVO_MPEGA_decode_frame;
  538.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  539.     CallPPCData->Args[1] = (ULONG)pcm;
  540.  
  541.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  542.  
  543.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  544.  
  545.     PPCWaitPort(ReplyPort);
  546.     PPCGetMessage(ReplyPort);
  547.     Return = CallPPCData->Return;
  548.  
  549.     if (SigTask != ThisTask)
  550.     {
  551.         PPCDeleteMessage(CallPPCMsg);
  552.         PPCDeletePort(ReplyPort);
  553.         PPCFreeVec(CallPPCData);
  554.     }
  555.  
  556.     return (LONG)Return;
  557. #elif defined(BUILD_WARPUP)
  558.     return (LONG)CallPPCFunc(WRAP_MPEGA_decode_frame, mpega_stream, pcm);
  559. #else
  560.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  561.     register char *stackptr __asm("sp");
  562.     struct Task *task;
  563.     long stackleft, stackreq = REQ_STACKSIZE;
  564.  
  565.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  566.  
  567.     MyPrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  568.     MyPrivateBase->stackswap.Args[1] = (ULONG)pcm;
  569.  
  570.     task = FindTask(NULL);
  571.     stackleft = stackptr - (char *)task->tc_SPLower;
  572.  
  573.     if (stackleft < stackreq)
  574.     {
  575.         char *newstack;
  576.  
  577.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  578.  
  579.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  580.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  581.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  582.  
  583.         StackSwap(&MyPrivateBase->stackswap.stack);
  584.  
  585.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_decode_frame((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (WORD **)MyPrivateBase->stackswap.Args[1]);
  586.  
  587.         StackSwap(&MyPrivateBase->stackswap.stack);
  588.  
  589.         FreeVec(newstack);
  590.         return (LONG)MyPrivateBase->stackswap.Return;
  591.     } else {
  592.         return WRAP_MPEGA_decode_frame((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (WORD **)MyPrivateBase->stackswap.Args[1]);
  593.     }
  594. #endif
  595. }
  596. #endif
  597.  
  598. #ifdef __MORPHOS__
  599. LONG LIB_MPEGA_seek(void)
  600. {
  601.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  602.     ULONG ms_time_position = (ULONG)REG_D0;
  603.     struct PrivateBase *PrivateBase = (struct PrivateBase *)REG_A6;
  604.     struct Task *task = FindTask(NULL);
  605.     ULONG stacksize, stackused, stackreq = REQ_STACKSIZE;
  606.  
  607.     NewGetTaskAttrsA(task, &stacksize, sizeof(stacksize), TASKINFOTYPE_STACKSIZE, NULL);
  608.     NewGetTaskAttrsA(task, &stackused, sizeof(stackused), TASKINFOTYPE_USEDSTACKSIZE, NULL);
  609.  
  610.     if ((stacksize - stackused) < stackreq)
  611.     {
  612.         char *newstack;
  613.  
  614.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  615.  
  616.         PrivateBase->stackswap.stack.stk_Lower = newstack;
  617.         PrivateBase->stackswap.stack.stk_Upper = (ULONG)newstack + stackreq;
  618.  
  619.         PrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  620.         PrivateBase->stackswap.Args[1] = (ULONG)ms_time_position;
  621.  
  622.         PrivateBase->stackswap.Return = NewPPCStackSwap(&PrivateBase->stackswap.stack, WRAP_MPEGA_seek, &PrivateBase->stackswap.Args);
  623.         FreeVec(newstack);
  624.     } else {
  625.         PrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_seek(mpega_stream, ms_time_position);
  626.     }
  627.  
  628.     return (LONG)PrivateBase->stackswap.Return;
  629. }
  630. #else
  631. LONG LIB LIB_MPEGA_seek(REG(a0, MPEGA_STREAM *mpega_stream), REG(d0, ULONG ms_time_position), REG(a6, struct PrivateBase *PrivateBase))
  632. {
  633. #ifdef BUILD_POWERUP
  634.     struct CallPPCData *CallPPCData;
  635.     APTR ReplyPort;
  636.     APTR CallPPCMsg;
  637.     ULONG Return;
  638.     APTR ThisTask = FindTask(NULL);
  639.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  640.  
  641.     /* Workaround for bad tasks that pass around the library base */
  642.     if (SigTask != ThisTask)
  643.     {
  644.         struct TagItem tmpTagList[1];
  645.  
  646.         tmpTagList[0].ti_Tag = TAG_DONE;
  647.         ReplyPort = PPCCreatePort(tmpTagList);
  648.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  649.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  650.     } else {
  651.         CallPPCData = PrivateBase->pv_CallPPCData;
  652.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  653.         ReplyPort = PrivateBase->pv_ReplyPort;
  654.     }
  655.  
  656.     CallPPCData->Type = MSGTYPE_CALL;
  657.     CallPPCData->PPCLVO = PPCLVO_MPEGA_seek;
  658.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  659.     CallPPCData->Args[1] = (ULONG)ms_time_position;
  660.  
  661.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  662.  
  663.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  664.  
  665.     PPCWaitPort(ReplyPort);
  666.     PPCGetMessage(ReplyPort);
  667.     Return = CallPPCData->Return;
  668.  
  669.     if (SigTask != ThisTask)
  670.     {
  671.         PPCDeleteMessage(CallPPCMsg);
  672.         PPCDeletePort(ReplyPort);
  673.         PPCFreeVec(CallPPCData);
  674.     }
  675.  
  676.     return (LONG)Return;
  677. #elif defined(BUILD_WARPUP)
  678.     return (LONG)CallPPCFunc(WRAP_MPEGA_seek, mpega_stream, ms_time_position);
  679. #else
  680.     register struct PrivateBase *MyPrivateBase __asm("a3") = PrivateBase;
  681.     register char *stackptr __asm("sp");
  682.     struct Task *task;
  683.     long stackleft, stackreq = REQ_STACKSIZE;
  684.  
  685.     __asm("":"=r"(stackptr));    /* force gcc to acknowledge usage of the sp register */
  686.  
  687.     MyPrivateBase->stackswap.Args[0] = (ULONG)mpega_stream;
  688.     MyPrivateBase->stackswap.Args[1] = (ULONG)ms_time_position;
  689.  
  690.     task = FindTask(NULL);
  691.     stackleft = stackptr - (char *)task->tc_SPLower;
  692.  
  693.     if (stackleft < stackreq)
  694.     {
  695.         char *newstack;
  696.  
  697.         if (!(newstack = AllocVec(stackreq, MEMF_PUBLIC))) return MPEGA_ERR_MEM;
  698.  
  699.         MyPrivateBase->stackswap.stack.stk_Lower = newstack;
  700.         MyPrivateBase->stackswap.stack.stk_Pointer = newstack + stackreq;
  701.         MyPrivateBase->stackswap.stack.stk_Upper = (ULONG)MyPrivateBase->stackswap.stack.stk_Pointer;
  702.  
  703.         StackSwap(&MyPrivateBase->stackswap.stack);
  704.  
  705.         MyPrivateBase->stackswap.Return = (ULONG)WRAP_MPEGA_seek((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (ULONG)MyPrivateBase->stackswap.Args[1]);
  706.  
  707.         StackSwap(&MyPrivateBase->stackswap.stack);
  708.  
  709.         FreeVec(newstack);
  710.         return (LONG)MyPrivateBase->stackswap.Return;
  711.     } else {
  712.         return WRAP_MPEGA_seek((MPEGA_STREAM *)MyPrivateBase->stackswap.Args[0], (ULONG)MyPrivateBase->stackswap.Args[1]);
  713.     }
  714. #endif
  715. }
  716. #endif
  717.  
  718. #ifdef __MORPHOS__
  719. LONG LIB_MPEGA_time(void)
  720. {
  721.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  722.     ULONG *ms_time_position = (ULONG *)REG_A1;
  723. #else
  724. LONG LIB LIB_MPEGA_time(REG(a0, MPEGA_STREAM *mpega_stream), REG(a1, ULONG *ms_time_position), REG(a6, struct PrivateBase *PrivateBase))
  725. {
  726. #endif
  727. #ifdef BUILD_POWERUP
  728.     struct CallPPCData *CallPPCData;
  729.     APTR ReplyPort;
  730.     APTR CallPPCMsg;
  731.     ULONG Return;
  732.     APTR ThisTask = FindTask(NULL);
  733.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  734.  
  735.     /* Workaround for bad tasks that pass around the library base */
  736.     if (SigTask != ThisTask)
  737.     {
  738.         struct TagItem tmpTagList[1];
  739.  
  740.         tmpTagList[0].ti_Tag = TAG_DONE;
  741.         ReplyPort = PPCCreatePort(tmpTagList);
  742.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  743.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  744.     } else {
  745.         CallPPCData = PrivateBase->pv_CallPPCData;
  746.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  747.         ReplyPort = PrivateBase->pv_ReplyPort;
  748.     }
  749.  
  750.     CallPPCData->Type = MSGTYPE_CALL;
  751.     CallPPCData->PPCLVO = PPCLVO_MPEGA_time;
  752.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  753.     CallPPCData->Args[1] = (ULONG)ms_time_position;
  754.  
  755.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  756.  
  757.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  758.  
  759.     PPCWaitPort(ReplyPort);
  760.     PPCGetMessage(ReplyPort);
  761.     Return = CallPPCData->Return;
  762.  
  763.     if (SigTask != ThisTask)
  764.     {
  765.         PPCDeleteMessage(CallPPCMsg);
  766.         PPCDeletePort(ReplyPort);
  767.         PPCFreeVec(CallPPCData);
  768.     }
  769.  
  770.     return (LONG)Return;
  771. #elif defined(BUILD_WARPUP)
  772.     return (LONG)CallPPCFunc(WRAP_MPEGA_time, mpega_stream, ms_time_position);
  773. #else
  774.     return WRAP_MPEGA_time(mpega_stream, ms_time_position);
  775. #endif
  776. }
  777.  
  778. #ifdef __MORPHOS__
  779. LONG LIB_MPEGA_find_sync(void)
  780. {
  781.     UBYTE *buffer = (UBYTE *)REG_A0;
  782.     LONG buffer_size = (LONG)REG_D0;
  783. #else
  784. LONG LIB LIB_MPEGA_find_sync(REG(a0, UBYTE *buffer), REG(d0, LONG buffer_size), REG(a6, struct PrivateBase *PrivateBase))
  785. {
  786. #endif
  787. #ifdef BUILD_POWERUP
  788.     struct CallPPCData *CallPPCData;
  789.     APTR ReplyPort;
  790.     APTR CallPPCMsg;
  791.     ULONG Return;
  792.     APTR ThisTask = FindTask(NULL);
  793.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  794.  
  795.     /* Workaround for bad tasks that pass around the library base */
  796.     if (SigTask != ThisTask)
  797.     {
  798.         struct TagItem tmpTagList[1];
  799.  
  800.         tmpTagList[0].ti_Tag = TAG_DONE;
  801.         ReplyPort = PPCCreatePort(tmpTagList);
  802.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  803.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  804.     } else {
  805.         CallPPCData = PrivateBase->pv_CallPPCData;
  806.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  807.         ReplyPort = PrivateBase->pv_ReplyPort;
  808.     }
  809.  
  810.     CallPPCData->Type = MSGTYPE_CALL;
  811.     CallPPCData->PPCLVO = PPCLVO_MPEGA_find_sync;
  812.     CallPPCData->Args[0] = (ULONG)buffer;
  813.     CallPPCData->Args[1] = (ULONG)buffer_size;
  814.  
  815.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  816.  
  817.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  818.  
  819.     PPCWaitPort(ReplyPort);
  820.     PPCGetMessage(ReplyPort);
  821.     Return = CallPPCData->Return;
  822.  
  823.     if (SigTask != ThisTask)
  824.     {
  825.         PPCDeleteMessage(CallPPCMsg);
  826.         PPCDeletePort(ReplyPort);
  827.         PPCFreeVec(CallPPCData);
  828.     }
  829.  
  830.     return (LONG)Return;
  831. #elif defined(BUILD_WARPUP)
  832.     return (LONG)CallPPCFunc(WRAP_MPEGA_find_sync, buffer, buffer_size);
  833. #else
  834.     return WRAP_MPEGA_find_sync(buffer, buffer_size);
  835. #endif
  836. }
  837.  
  838. #ifdef __MORPHOS__
  839. LONG LIB_MPEGA_scale(void)
  840. {
  841.     MPEGA_STREAM *mpega_stream = (MPEGA_STREAM *)REG_A0;
  842.     LONG scale_percent = (LONG)REG_D0;
  843. #else
  844. LONG LIB LIB_MPEGA_scale(REG(a0, MPEGA_STREAM *mpega_stream), REG(d0, LONG scale_percent), REG(a6, struct PrivateBase *PrivateBase))
  845. {
  846. #endif
  847. #ifdef BUILD_POWERUP
  848.     struct CallPPCData *CallPPCData;
  849.     APTR ReplyPort;
  850.     APTR CallPPCMsg;
  851.     ULONG Return;
  852.     APTR ThisTask = FindTask(NULL);
  853.     APTR SigTask = ((struct MsgPort *)PrivateBase->pv_ReplyPort)->mp_SigTask;    /* !!!HACK!!! */
  854.  
  855.     /* Workaround for bad tasks that pass around the library base */
  856.     if (SigTask != ThisTask)
  857.     {
  858.         struct TagItem tmpTagList[1];
  859.  
  860.         tmpTagList[0].ti_Tag = TAG_DONE;
  861.         ReplyPort = PPCCreatePort(tmpTagList);
  862.         CallPPCMsg = PPCCreateMessage(ReplyPort, sizeof(struct CallPPCData));
  863.         CallPPCData = PPCAllocVec(sizeof(struct CallPPCData), MEMF_PUBLIC);
  864.     } else {
  865.         CallPPCData = PrivateBase->pv_CallPPCData;
  866.         CallPPCMsg = PrivateBase->pv_CallPPCMsg;
  867.         ReplyPort = PrivateBase->pv_ReplyPort;
  868.     }
  869.  
  870.     CallPPCData->Type = MSGTYPE_CALL;
  871.     CallPPCData->PPCLVO = PPCLVO_MPEGA_scale;
  872.     CallPPCData->Args[0] = (ULONG)mpega_stream;
  873.     CallPPCData->Args[1] = (ULONG)scale_percent;
  874.  
  875.     PPCCacheClearE(NULL, 0xffffffff, CACRF_ClearD);
  876.  
  877.     PPCSendMessage(PrivateBase->pv_PPCPort, CallPPCMsg, CallPPCData, sizeof(struct CallPPCData), 0x12345678);
  878.  
  879.     PPCWaitPort(ReplyPort);
  880.     PPCGetMessage(ReplyPort);
  881.     Return = CallPPCData->Return;
  882.  
  883.     if (SigTask != ThisTask)
  884.     {
  885.         PPCDeleteMessage(CallPPCMsg);
  886.         PPCDeletePort(ReplyPort);
  887.         PPCFreeVec(CallPPCData);
  888.     }
  889.  
  890.     return (LONG)Return;
  891. #elif defined(BUILD_WARPUP)
  892.     return (LONG)CallPPCFunc(WRAP_MPEGA_scale, mpega_stream, scale_percent);
  893. #else
  894.     return WRAP_MPEGA_scale(mpega_stream, scale_percent);
  895. #endif
  896. }
  897.